// 输入网格顶点位置，输出随机向量
vec2 hash2d(vec2 p){
    return  -1.0 + 2.0 * fract(
        sin(
            vec2(
                dot(p, vec2(127.1,311.7)),
                dot(p, vec2(269.5,183.3))
            )
        ) * 43758.5453
    );
}

vec3 valueNoise(vec2 uv)
{
    //int position used for random number generation
    vec2 intPos = floor( uv );
    
    //frac position used for interpolation
    vec2 fracPos = fract( uv );
    
    //get the interpolation weights(u) and weights derivatives(du)
#if 1
    // quintic interpolation
    vec2 u = fracPos * fracPos * fracPos * (fracPos *( fracPos * 6.0 - 15.0) + 10.0);
    vec2 du = 30.0 * fracPos * fracPos * (fracPos * (fracPos - 2.0) + 1.0);
#else
    // cubic interpolation
    vec2 u = fracPos * fracPos * (3.0 - 2.0 * fracPos);
    vec2 du = 6.0 * fracPos *( 1.0 - fracPos);
#endif    
    
    //generate 4 different random value on 4 neighbor vertices
    float va = hash2d( intPos + vec2(0.0, 0.0) ).y;
    float vb = hash2d( intPos + vec2(1.0, 0.0) ).y;
    float vc = hash2d( intPos + vec2(0.0, 1.0) ).y;
    float vd = hash2d( intPos + vec2(1.0, 1.0) ).y;
    
    float k0 = va;
    float k1 = vb - va;//horizontal
    float k2 = vc - va;//vertical
    float k4 = va - vb - vc + vd;
    
    //mix(mix(va, vb, u.x), mix(vc, vd, u.x), u.y);
    float value = k0 + k1 * u.x + k2 * u.y + k4 * u.x * u.y;
    
    //vec2(d value / du.xy)
    vec2 derivative = du * (u.yx * k4 + vec2(k1, k2));
    return vec3(value, derivative); 
}


#define SCALE 100. // 将平面分为 4 × 4 个正方形网格
float noise(vec2 p) {
  p *= SCALE;
  vec3 noiseValue = valueNoise(p);
  return noiseValue.x;
}

void mainImage( out vec4 fragColor, in vec2 fragCoord ){
    vec2 st = fragCoord.xy / iResolution.xy;
    float value = noise(st);
    vec3 color = vec3(value);
    fragColor = vec4(color,1.0);
}